// 公共吐司提示
export function Toast (data, icon = 'none') {
    return uni.showToast({
        title: data,
        icon: icon,
        duration: 1500
    });
}

// 去除首尾空格
export function trim (str) {
    return str.replace(/(^\s*)|(\s*$)/g, "");
}

// 结合 async/await 实现阻塞线程
export function sleep(timeout) {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}

// 全替换
export function replaceAll(str, searchValue, replaceValue) {
    return str.split(searchValue).join(replaceValue);
}
// 脱敏
export function desensitize(str, formatter) {
    if (!str && str !== 0) {
        return str;
    }
    if (!formatter) {
        formatter = 'xxx****xxxx';
    }
    if (formatter.indexOf('*') == -1) {
        // 返回全星号
        return '*'.repeat(str.length);
    }
    // 格式化字符串连续字符部分
    const formatterParts = [];
    // 临时变量
    let lastChar = '',
        lastString = '';
    // 将格式化字符串按照连续字符分割成多个部分
    formatter
        .toString()
        .split('')
        .forEach(char => {
            if (char !== lastChar) {
                if (lastString) {
                    formatterParts.push(lastString);
                    lastString = '';
                }
                lastChar = char;
            }
            lastString += char;
        });
    // 最后部分
    if (lastString) {
        formatterParts.push(lastString);
    }
    // 星号部分个数（出现多处星号部分默认为严格模式）
    const starPartCount = formatterParts.filter(part => part.includes('*')).length;
    // 是否严格模式（出现多处星号部分默认为严格模式）
    const isStrict = starPartCount > 1;
    // 暴露部分总长度
    const totalLength = formatter.replace(/\*/g, '').length + (isStrict ? formatter.replace(/[^*]/g, '').length : starPartCount);
    // 需要减少的长度
    let reduceLength = totalLength - str.length;
    // 循环减少长度直至达到要求
    while (reduceLength > 0) {
        let flag = false;
        for (let i = formatterParts.length - 1; i >= 0; i--) {
            if (formatterParts[i].length == 1) {
                continue;
            }
            if (formatterParts[i].includes('*') && !isStrict) {
                continue;
            }
            formatterParts[i] = formatterParts[i].substring(0, formatterParts[i].length - 1);
            reduceLength--;
            flag = true;
            if (reduceLength <= 0) {
                break;
            }
        }
        if (!flag) {
            break;
        }
    }
    // 仍旧达不到要求
    if (reduceLength > 0) {
        // 返回全星号
        return '*'.repeat(str.length);
    }
    // 正则
    let regString = '',
        // 正则（严格模式）
        regStringStrict = '',
        // 替换的正则
        replaceString = '',
        // 替换索引
        replaceIndex = 1;
    // 产生正则
    formatterParts.forEach(part => {
        if (part.includes('*')) {
            regString += `(?:.+)`;
            regStringStrict += `(?:.{${part.length},})`;
            replaceString += part;
        } else {
            regString += `(.{${part.length}})`;
            regStringStrict += `(.{${part.length}})`;
            replaceString += '$' + replaceIndex++;
        }
    });
    // 最终的正则匹配式
    const reg = isStrict ? new RegExp(String.raw`^${regStringStrict}$`) : new RegExp(String.raw`^${regString}$`);
    // 替换结果
    const result = str.replace(reg, replaceString);
    // 替换后与替换前没区别
    if (result == str) {
        // 返回全星号
        return '*'.repeat(str.length);
    }
    // 返回结果
    return result;
}

/**
 * 判断 v1 的版本号是否大于 v2 版本号
 * 作者：kzl
 * @param {String} v1 - 版本字符串 格式 1.2.0
 * @param {String} v2 - 版本字符串 格式 1.2.2
 * @returns {Number}  - 0: 表示 版本相同, 1: 表示 v1 版本大于 v2, -1: 表示v1 版本小于v2
 */
export function compareVersion(v1, v2) {
    let cpResult;
    let i = 0;
    const arr1 = v1.replace(/[^0-9.]/, '').split('.');
    const arr2 = v2.replace(/[^0-9.]/, '').split('.');
    while (true) {
        const s1 = arr1[i];
        const s2 = arr2[i++];
        if (s1 === undefined || s2 === undefined) {
            cpResult = arr1.length - arr2.length;
            break;
        }
        if (s1 === s2) continue;
        cpResult = s1 - s2;
        break;
    }
    return cpResult > 0 ? 1 : cpResult === 0 ? 0 : -1;
}

// 根据小数位数格式化数字（四舍五入）
export function formartDecimal(num, length) {
    if (isNaN(num) || !length) {
        return Math.round(num);
    }
    length = length ? parseInt(length) : 0;
    if (length <= 0) {
        return Math.round(num);
    }
    return Math.round(num * Math.pow(10, length)) / Math.pow(10, length);
}
// 获取指定范围内的随机整数
export function getRandom(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 下载二进制对象
export function downloadBlob(blob, fileName) {
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName || `文件${+Date.now()}.xlsx`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
}
// 下载文件
export function downloadFile(url, fileName) {
    return new Promise(resolve => {
        fetch(url)
            .then(res => res.blob())
            .then(blob => {
                downloadBlob(blob, fileName);
                resolve(true);
            })
            .catch(() => resolve(false));
    });
}

//  判断当前是否为全屏状态
export function isFullScreen() {
    return window.top.document.fullscreenElement || false;
}
// 全屏状态判断以及切换
export function toggleFullScreen() {
    if (!isFullScreen()) {
        const de = window.top.document.documentElement;
        const rfs = de.RequestFullScreen || de.mozRequestFullScreen || de.webkitRequestFullScreen || de.msRequestFullscreen;
        rfs && rfs.call(de);
    } else {
        const d = window.top.document;
        const efs = d.exitFullScreen || d.mozCancelFullScreen || d.webkitExitFullscreen || d.msExitFullscreen;
        efs && efs.call(d);
    }
}

// 非空校验处理，如果空默认返回 --
export function nullFilter(str, strIfNull) {
    if (str || str === 0) {
        return str;
    } else {
        return strIfNull || '--';
    }
}

const objectTypeDetermination = {
    isNull(object) {
        return object === null;
    },
    isUndefined(object) {
        return object === undefined;
    },
    isNaN(object) {
        return Number.isNaN(object);
    },
    isZero(object) {
        return object === 0;
    },
    isFalse(object) {
        if (objectTypeDetermination.isNull(object) || objectTypeDetermination.isUndefined(object) || objectTypeDetermination.isNaN(object) || objectTypeDetermination.isZero(object) || !object) {
            return true;
        }
        return false;
    },
    isTrue(object) {
        return !objectTypeDetermination.isFalse(object);
    },
    isNumber(object) {
        return typeof object === 'number';
    },
    isString(object) {
        return typeof object === 'string';
    },
    isArray(object) {
        return objectTypeDetermination.isTrue(object) && Object.prototype.toString.call(object) === '[object Array]';
    },
    isObject(object) {
        return objectTypeDetermination.isTrue(object) && Object.prototype.toString.call(object) === '[object Object]';
    },
    isFunction(object) {
        return objectTypeDetermination.isTrue(object) && object.constructor === Function;
    },
    getObjectType(object) {
        if (objectTypeDetermination.isNull(object)) return 'null';
        if (objectTypeDetermination.isUndefined(object)) return 'undefined';
        if (objectTypeDetermination.isNaN(object)) return 'NaN';
        if (objectTypeDetermination.isFalse(object)) return 'false';
        if (objectTypeDetermination.isTrue(object)) return 'true';
        if (objectTypeDetermination.isNumber(object)) return 'Number';
        if (objectTypeDetermination.isString(object)) return 'String';
        if (objectTypeDetermination.isArray(object)) return 'Array';
        if (objectTypeDetermination.isObject(object)) return 'Object';
        if (objectTypeDetermination.isFunction(object)) return 'Function';
    },
};
// 是否为 null
export function isNull(object) {
    return objectTypeDetermination.isNull(object);
}
// 是否为 undefined
export function isUndefined(object) {
    return objectTypeDetermination.isUndefined(object);
}
// 是否为 NaN
export function isNaN(object) {
    return objectTypeDetermination.isNaN(object);
}
// 是否为 0
export function isZero(object) {
    return objectTypeDetermination.isZero(object);
}
// 是否为 false
export function isFalse(object) {
    return objectTypeDetermination.isFalse(object);
}
// 是否为 true
export function isTrue(object) {
    return objectTypeDetermination.isTrue(object);
}
// 是否为 Number
export function isNumber(object) {
    return objectTypeDetermination.isNumber(object);
}
// 是否为字符串
export function isString(object) {
    return objectTypeDetermination.isString(object);
}
// 是否为数组
export function isArray(object) {
    return objectTypeDetermination.isArray(object);
}
// 是否为对象
export function isObject(object) {
    return objectTypeDetermination.isObject(object);
}
// 是否为函数
export function isFunction(object) {
    return objectTypeDetermination.isFunction(object);
}
// 返回对象类型
export function getObjectType(object) {
    return objectTypeDetermination.getObjectType(object);
}
// 判断传入值是否为空值
export function isEmpty(object) {
    if (!object && object !== 0) {
        // 如果传入值是字符型/数值型，则执行这里判断它是否空值
        return true;
    }
    if (Array.isArray(object) && object.length == 0) {
        // 如果传入值是数组，则判断它是否为空数组
        return true;
    }
    if (Object.prototype.toString.call(object) === '[object Object]' && Reflect.ownKeys(object).length == 0) {
        // 如果传入值是对象，则判断它是否为空对象
        return true;
    }
    return false;
}

/**
 * 判断对象是否存在某个字段
 * @param {Object} data
 * @param {String} field
 * @returns {Boolean}
 */
export function hasProperty(data, field) {
    return data && Object.prototype.hasOwnProperty.call(data, field);
}

/**
 * 文件读取、canves读取
 * @param {file} 图片文件
 * @param {Function} callback 回调
 * @returns {canvas, ctx}
 */
export const fileReadAsCanves = (file, callback) => {
    // 创建一个HTML5的FileReader对象
    let reader = new FileReader();
    //创建一个img对象
    let img = new Image();
    if (file) {
        reader.readAsDataURL(file);
    }
    reader.onload = e => {
        img.src = e.target.result;
        // base64地址图片加载完毕后执行
        img.onload = function () {
            // 缩放图片需要的canvas（也可以在DOM中直接定义canvas标签，这样就能把压缩完的图片不转base64也能直接显示出来）
            let canvas = document.createElement('canvas');
            let ctx = canvas.getContext('2d');
            // 图片原始尺寸
            let originWidth = this.width;
            let originHeight = this.height;
            //对图片进行缩放
            canvas.width = originWidth;
            canvas.height = originHeight;
            // 清除画布
            ctx.clearRect(0, 0, originWidth, originHeight);
            // 图片压缩
            ctx.drawImage(img, 0, 0, originWidth, originHeight);
            /*第一个参数是创建的img对象；第二三个参数是左上角坐标，后面两个是画布区域宽高*/

            // 回调
            callback(canvas, ctx);
        };
    };
};
/**
 * 图片压缩
 * @param {file} 图片文件
 * @param {Number} quality 压缩质量
 * @param {Function} callback 回调
 * @returns {blobs, file.name}
 */
export const imageCompress = (file, quality, callback) => {
    fileReadAsCanves(file, (canvas, ctx) => {
        canvas.toBlob(
            blobs => {
                callback(blobs, file.name);
            },
            'image/jpeg',
            quality
        );
    });
};
/**
 * 图片加水印
 * @param {file} 图片文件
 * @param {Object} watermark - 水印信息
 * @param {Function} callback 回调
 * @returns {blobs, file.name}
 */
export const imageAddWatermark = (file, watermark, callback) => {
    fileReadAsCanves(file, (canvas, ctx) => {
        let fontLineHieht = 0;
        for (let i = 0, len = watermark.data.length; i < len; i++) {
            let item = watermark.data[i];

            ctx.fillStyle = item.style?.color || watermark.color || 'red';
            ctx.font = `${item.style?.fontSize || watermark.fontSize || 30}px Arial`;
            fontLineHieht = (item.style?.fontSize || watermark.fontSize || 30) + 10;

            // 左上
            if (item.position == 'topLeft') {
                ctx.textAlign = 'left';
                for (let j = 0, len_1 = item.text.length; j < len_1; j++) {
                    ctx.fillText(item.text[j], 10, (j + 1) * fontLineHieht);
                }
            }
            // 右上
            if (item.position == 'topRight') {
                ctx.textAlign = 'right';
                for (let j = 0, len_1 = item.text.length; j < len_1; j++) {
                    ctx.fillText(item.text[j], canvas.width - 10, (j + 1) * fontLineHieht);
                }
            }
            // 左下
            if (item.position == 'bottomLeft') {
                ctx.textAlign = 'left';
                for (let j = 0, len_1 = item.text.length; j < len_1; j++) {
                    ctx.fillText(item.text[j], 10, canvas.height - 10 - j * fontLineHieht);
                }
            }
            // 右下
            if (item.position == 'bottomRight') {
                ctx.textAlign = 'right';
                for (let j = 0, len_1 = item.text.length; j < len_1; j++) {
                    ctx.fillText(item.text[j], canvas.width - 10, canvas.height - 10 - j * fontLineHieht);
                }
            }
            // 中间
            if (item.position == 'center') {
                ctx.textAlign = 'left';
                for (let j = 0, len_1 = item.text.length; j < len_1; j++) {
                    ctx.fillText(item.text[j], (canvas.width - ctx.measureText(item.text[j]).width) / 2, canvas.height / 2);
                }
            }
        }

        // 输出blobs
        canvas.toBlob(
            blobs => {
                callback(blobs, file.name);
            },
            'image/jpeg',
            1
        );
    });
};

/* 飞入动画
 * fromEl: 点击位置dom
 * toEl: 飞入目标dom
 * duration: 动画时长
 * icon: 图标
 */
export const flyToAnimation = (fromEl, toEl, duration = 0.5, icon) => {
    // 默认图标
    let defaultIcon =
        '';
    // 创建图标容器
    let taskEl = document.createElement('div');
    // 获取点击位置元素坐标
    let fromElStyle = fromEl.getBoundingClientRect();
    // 飞入动画样式
    let taskElStyle = `width: 20px; height: 20px; position: absolute; z-index: 9999;
        background: url(${icon || defaultIcon}) center no-repeat; background-size: 100% 100%;
        left: ${parseInt(fromElStyle.left) + parseInt(fromElStyle.width) / 2}px;
        top: ${parseInt(fromElStyle.top)}px;
        transition: all ${duration}s ease-in;`;
    taskEl.setAttribute('style', taskElStyle);
    // 插入飞入动画dom
    document.body.appendChild(taskEl);
    // 动画位移量
    let translatePosition = {
        x: toEl.offsetLeft - parseInt(fromElStyle.left),
        y: toEl.offsetTop - fromElStyle.top,
    };
    // 创建动画效果
    taskEl.style.transform = `translate3d(${translatePosition.x}px, ${translatePosition.y}px, 0)`;
    taskEl.style.transition = 'all 0.5s ease-in';
    // 动画完成后移除taskEl
    taskEl.addEventListener('transitionend', () => {
        document.body.removeChild(taskEl);
    });
};
